/*
 * Copyright (c) 2011-2014, fortiss GmbH.
 * Licensed under the Apache License, Version 2.0.
 *
 * Use, modification and distribution are subject to the terms specified
 * in the accompanying license file LICENSE.txt located at the root directory
 * of this software distribution. A copy is available at
 * http://chromosome.fortiss.org/.
 *
 * This file is part of CHROMOSOME.
 *
 * $Id: systemComponentWrapper.c 7774 2014-03-11 17:38:48Z geisinger $
 */

/**
 * \file
 *         Component wrapper - implements interface of a component
 *              to the data handler
 *
 * \author
 *         This file has been generated by the CHROMOSOME Modeling Tool (XMT)
 *         (fortiss GmbH).
 */

/******************************************************************************/
/***   Includes                                                             ***/
/******************************************************************************/
#include "rOSGateway/adv/system/include/systemComponentWrapper.h"

#include "xme/core/dataHandler/include/dataHandler.h"
#include "xme/core/log.h"

#ifdef XME_MULTITHREAD
#include "xme/hal/include/tls.h"
#endif // #ifdef XME_MULTITHREAD

/******************************************************************************/
/***   Type definitions                                                     ***/
/******************************************************************************/
/**
 * \brief Structure for storing information about the input ports.
 */
typedef struct
{
    xme_core_dataManager_dataPacketId_t dataPacketId; ///< The data packet id.
    xme_core_component_portState_t state; ///< State of the port. Denotes whether the port is locked, whether data and/or attributes have been read from it and whether an error occurred.
} inputPort_t;

/**
 * \brief Structure for storing information about the output ports.
 */
typedef struct
{
    xme_core_dataManager_dataPacketId_t dataPacketId; ///< The data packet id.
    xme_core_component_portState_t state; ///< State of the port. Denotes whether the port is locked, whether data and/or attributes have been written to it and whether an error occurred.
} outputPort_t;

/******************************************************************************/
/***   Variables                                                            ***/
/******************************************************************************/
/**
 * \brief Number of times this component wrapper has been initialized.
 */
static uint16_t initializationCount = 0U;

/**
 * \brief Array storing information about the input ports.
 */
static inputPort_t inputPorts[] = {
    {XME_CORE_DATAMANAGER_DATAPACKETID_INVALID, { 0U } }, // system.messageStatus
    {XME_CORE_DATAMANAGER_DATAPACKETID_INVALID, { 0U } }, // system.getSum
    {XME_CORE_DATAMANAGER_DATAPACKETID_INVALID, { 0U } }  // system.receivedDifference
};

/**
 * \brief Array storing information about the output ports.
 */
static outputPort_t outputPorts[] = {
    {XME_CORE_DATAMANAGER_DATAPACKETID_INVALID, { 0U } }, // system.message
    {XME_CORE_DATAMANAGER_DATAPACKETID_INVALID, { 0U } }, // system.sendSum
    {XME_CORE_DATAMANAGER_DATAPACKETID_INVALID, { 0U } }  // system.getDifference
};

/**
 * \brief Size of inputPorts array.
 */
static const uint8_t inputPortCount = sizeof(inputPorts) / sizeof(inputPorts[0]);

/**
 * \brief Size of outputPorts array.
 */
static const uint8_t outputPortCount = sizeof(outputPorts) / sizeof(outputPorts[0]);

#ifdef XME_MULTITHREAD
static xme_hal_tls_handle_t inputPortAccessed = XME_HAL_TLS_INVALID_TLS_HANDLE; ///< Bitmap storing whether a specific thread has accessed an input port in multithreading scenarios.
#endif // #ifdef XME_MULTITHREAD

#ifdef XME_MULTITHREAD
static xme_hal_tls_handle_t outputPortAccessed = XME_HAL_TLS_INVALID_TLS_HANDLE; ///< Bitmap storing whether a specific thread has accessed an output port in multithreading scenarios.
#endif // #ifdef XME_MULTITHREAD

/******************************************************************************/
/***   Implementation                                                       ***/
/******************************************************************************/
xme_status_t
rOSGateway_adv_system_systemComponentWrapper_init(void)
{
    if (0U == initializationCount)
    {
        #ifdef XME_MULTITHREAD
        if (XME_HAL_TLS_INVALID_TLS_HANDLE == inputPortAccessed)
        {
            inputPortAccessed = xme_hal_tls_alloc((inputPortCount + 7U) / 8U);
            XME_ASSERT(XME_HAL_TLS_INVALID_TLS_HANDLE != inputPortAccessed);
        }
        if (XME_HAL_TLS_INVALID_TLS_HANDLE == outputPortAccessed)
        {
            outputPortAccessed = xme_hal_tls_alloc((outputPortCount + 7U) / 8U);
            XME_ASSERT(XME_HAL_TLS_INVALID_TLS_HANDLE != outputPortAccessed);
        }
        #endif // #ifdef XME_MULTITHREAD
    }

    initializationCount++;

    return XME_STATUS_SUCCESS;
}

void
rOSGateway_adv_system_systemComponentWrapper_fini(void)
{
    XME_ASSERT_NORVAL(initializationCount > 0U);
    initializationCount--;

    if (0U == initializationCount)
    {
        #ifdef XME_MULTITHREAD
        if (XME_HAL_TLS_INVALID_TLS_HANDLE != inputPortAccessed)
        {
            xme_hal_tls_free(inputPortAccessed);
        }
        if (XME_HAL_TLS_INVALID_TLS_HANDLE != outputPortAccessed)
        {
            xme_hal_tls_free(outputPortAccessed);
        }
        #endif // #ifdef XME_MULTITHREAD
    }
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_receivePort
(
    xme_core_dataManager_dataPacketId_t dataPacketId,
    rOSGateway_adv_system_systemComponentWrapper_internalPortId_t componentInternalPortId
)
{
    XME_CHECK
    (
        (inputPortCount + outputPortCount) > componentInternalPortId,
        XME_STATUS_INVALID_PARAMETER
    );

    if (componentInternalPortId < inputPortCount)
    {
        inputPorts[componentInternalPortId].dataPacketId = dataPacketId;
        inputPorts[componentInternalPortId].state.dataValid = 0;
        inputPorts[componentInternalPortId].state.attributesValid = 0;
        inputPorts[componentInternalPortId].state.locked = 0;
        inputPorts[componentInternalPortId].state.error = 0;
    }
    else
    {
        uint8_t outputPortIndex = componentInternalPortId - inputPortCount;
        outputPorts[outputPortIndex].dataPacketId = dataPacketId;
        outputPorts[outputPortIndex].state.dataValid = 0;
        outputPorts[outputPortIndex].state.attributesValid = 0;
        outputPorts[outputPortIndex].state.locked = 0;
        outputPorts[outputPortIndex].state.error = 0;
    }

    return XME_STATUS_SUCCESS;
}

void
rOSGateway_adv_system_systemComponentWrapper_completeReadOperations(void)
{
    uint8_t inputPortIndex;

    for (inputPortIndex = 0U; inputPortIndex < inputPortCount; inputPortIndex++)
    {
        // This is a no-operation in case the port has not been read
        (void) rOSGateway_adv_system_systemComponentWrapper_readNextPacket(inputPortIndex);
    }
}

void
rOSGateway_adv_system_systemComponentWrapper_completeWriteOperations(void)
{
    uint8_t outputPortIndex;

    for (outputPortIndex = inputPortCount; outputPortIndex < inputPortCount + outputPortCount; outputPortIndex++)
    {
        // This is a no-operation in case the port has not been accessed
        (void) rOSGateway_adv_system_systemComponentWrapper_writeNextPacket(outputPortIndex);
    }
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_readPortMessageStatus
(
    const ROSGateway_topic_status_t* data
)
{
    uint8_t inputPortIndex;
    unsigned int bytesRead;
    xme_status_t status;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    XME_CHECK(NULL != data, XME_STATUS_INVALID_PARAMETER);

    inputPortIndex = (uint8_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_MESSAGESTATUS;

#ifdef XME_MULTITHREAD
    XME_ASSERT(inputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(inputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[inputPortIndex / 8U] & (1 << (inputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!inputPorts[inputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startReadOperation(inputPorts[inputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[inputPortIndex / 8U] |= (1 << (inputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        inputPorts[inputPortIndex].state.locked = 1;
    }

    status = xme_core_dataHandler_readData
    (
        inputPorts[inputPortIndex].dataPacketId,
        (void*)data,
        (uint32_t)sizeof(ROSGateway_topic_status_t),
        &bytesRead
    );

    if (XME_STATUS_SUCCESS == status)
    {
        inputPorts[inputPortIndex].state.dataValid = 1;
    }
    else
    {
        inputPorts[inputPortIndex].state.error = 1;
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_readPortReceivedDifference
(
    const ROSGateway_topic_differenceResponse_t* data
)
{
    uint8_t inputPortIndex;
    unsigned int bytesRead;
    xme_status_t status;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    XME_CHECK(NULL != data, XME_STATUS_INVALID_PARAMETER);

    inputPortIndex = (uint8_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_RECEIVEDDIFFERENCE;

#ifdef XME_MULTITHREAD
    XME_ASSERT(inputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(inputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[inputPortIndex / 8U] & (1 << (inputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!inputPorts[inputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startReadOperation(inputPorts[inputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[inputPortIndex / 8U] |= (1 << (inputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        inputPorts[inputPortIndex].state.locked = 1;
    }

    status = xme_core_dataHandler_readData
    (
        inputPorts[inputPortIndex].dataPacketId,
        (void*)data,
        (uint32_t)sizeof(ROSGateway_topic_differenceResponse_t),
        &bytesRead
    );

    if (XME_STATUS_SUCCESS == status)
    {
        inputPorts[inputPortIndex].state.dataValid = 1;
    }
    else
    {
        inputPorts[inputPortIndex].state.error = 1;
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_readRequestHandlerPortGetSum
(
    const ROSGateway_topic_sumRequest_t* data,
    const xme_core_component_requestDataHandle_t* requestDataHandle
)
{
    uint8_t inputPortIndex;
    unsigned int bytesRead;
    xme_status_t status;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    XME_CHECK(NULL != data, XME_STATUS_INVALID_PARAMETER);
    XME_CHECK(NULL != requestDataHandle, XME_STATUS_INVALID_PARAMETER);

    inputPortIndex = (uint8_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_GETSUM;

#ifdef XME_MULTITHREAD
    XME_ASSERT(inputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(inputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[inputPortIndex / 8U] & (1 << (inputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!inputPorts[inputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startReadOperation(inputPorts[inputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[inputPortIndex / 8U] |= (1 << (inputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        inputPorts[inputPortIndex].state.locked = 1;
    }

    // Write channelID attribute from request to requestHandle
    status = rOSGateway_adv_system_systemComponentWrapper_readInputPortAttribute
    (
        (rOSGateway_adv_system_systemComponentWrapper_internalPortId_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_GETSUM,
        XME_CORE_ATTRIBUTE_KEY_CHANNELID,
        (void*)requestDataHandle,
        (uint32_t)sizeof(xme_core_component_requestDataHandle_t)
    );
    XME_CHECK_MSG_REC
    (
        XME_STATUS_SUCCESS == status,
        XME_STATUS_INTERNAL_ERROR,
        {
            inputPorts[inputPortIndex].state.error = 1;
        },
        XME_LOG_ERROR,
        "%s:%d rOSGateway_adv_system_systemComponentWrapper_readRequestHandlerPortGetSum: Reading channel ID attribute from port failed. This is attribute is mandatory for request/response communication. Message cannot be delivered.\n",
        __FILE__,
        __LINE__
    );
    inputPorts[inputPortIndex].state.attributesValid = 1;

    // Read topic data
    status = xme_core_dataHandler_readData
    (
        inputPorts[inputPortIndex].dataPacketId,
        (void*)data,
        (uint32_t)sizeof(ROSGateway_topic_sumRequest_t),
        &bytesRead
    );

    if (XME_STATUS_SUCCESS == status)
    {
        inputPorts[inputPortIndex].state.dataValid = 1;
    }
    else
    {
        inputPorts[inputPortIndex].state.error = 1;
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_writePortMessage
(
    const ROSGateway_topic_message_t* const data
)
{
    uint8_t outputPortIndex;
    xme_status_t status;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    outputPortIndex = ((uint8_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_MESSAGE) - inputPortCount;

    XME_CHECK_REC
    (
        NULL != data,
        XME_STATUS_SUCCESS,
        {
            outputPorts[outputPortIndex].state.dataValid = 0;
        }
    );

#ifdef XME_MULTITHREAD
    XME_ASSERT(outputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(outputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[outputPortIndex / 8U] & (1 << (outputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!outputPorts[outputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startWriteOperation(outputPorts[outputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[outputPortIndex / 8U] |= (1 << (outputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        outputPorts[outputPortIndex].state.locked = 1;
    }

    status = xme_core_dataHandler_writeData
    (
        outputPorts[outputPortIndex].dataPacketId,
        (void*)data,
        (uint32_t)sizeof(ROSGateway_topic_message_t)
    );

    if (XME_STATUS_SUCCESS == status)
    {
        outputPorts[outputPortIndex].state.dataValid = 1;
    }
    else
    {
        outputPorts[outputPortIndex].state.error = 1;

        XME_LOG(XME_LOG_ERROR,
            "[systemComponentWrapper] writePortMessage(): Writing to port failed. Data Handler returned error code %d.\n",
            status);
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_writePortGetDifference
(
    const ROSGateway_topic_differenceRequest_t* const data
)
{
    uint8_t outputPortIndex;
    xme_status_t status;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    outputPortIndex = ((uint8_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_GETDIFFERENCE) - inputPortCount;

    XME_CHECK_REC
    (
        NULL != data,
        XME_STATUS_SUCCESS,
        {
            outputPorts[outputPortIndex].state.dataValid = 0;
        }
    );

#ifdef XME_MULTITHREAD
    XME_ASSERT(outputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(outputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[outputPortIndex / 8U] & (1 << (outputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!outputPorts[outputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startWriteOperation(outputPorts[outputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[outputPortIndex / 8U] |= (1 << (outputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        outputPorts[outputPortIndex].state.locked = 1;
    }

    status = xme_core_dataHandler_writeData
    (
        outputPorts[outputPortIndex].dataPacketId,
        (void*)data,
        (uint32_t)sizeof(ROSGateway_topic_differenceRequest_t)
    );

    if (XME_STATUS_SUCCESS == status)
    {
        outputPorts[outputPortIndex].state.dataValid = 1;
    }
    else
    {
        outputPorts[outputPortIndex].state.error = 1;

        XME_LOG(XME_LOG_ERROR,
            "[systemComponentWrapper] writePortGetDifference(): Writing to port failed. Data Handler returned error code %d.\n",
            status);
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_writeResponseSenderPortSendSum
(
    const ROSGateway_topic_sumResponse_t* const data,
    const xme_core_component_requestDataHandle_t* const requestDataHandle
)
{
    uint8_t outputPortIndex;
    xme_status_t status;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    XME_CHECK(NULL != requestDataHandle, XME_STATUS_INVALID_PARAMETER);

    outputPortIndex = ((uint8_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_SENDSUM) - inputPortCount;

    // NULL == data means we should not write any data
    XME_CHECK_REC
    (
        NULL != data,
        XME_STATUS_SUCCESS,
        {
            outputPorts[outputPortIndex].state.error = 1;
        }
    );

#ifdef XME_MULTITHREAD
    XME_ASSERT(outputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(outputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[outputPortIndex / 8U] & (1 << (outputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!outputPorts[outputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startWriteOperation(outputPorts[outputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[outputPortIndex / 8U] |= (1 << (outputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        outputPorts[outputPortIndex].state.locked = 1;
    }

    XME_CHECK_MSG_REC
    (
        (xme_core_component_requestDataHandle_t)XME_CORE_COMPONENT_INVALID_REQUEST_DATA_HANDLE != *requestDataHandle,
        XME_STATUS_INVALID_PARAMETER,
        {
            outputPorts[outputPortIndex].state.error = 1;
        },
        XME_LOG_WARNING,
        "rOSGateway_adv_system_systemComponentWrapper_writeResponseSenderPortSendSum: Given requestDataHandle is invalid.\n"
    );

    // Write requestDataHandle, which is also the channelID of the request, to the channel ID attribute of the response
    status = rOSGateway_adv_system_systemComponentWrapper_writeOutputPortAttribute
    (
        (rOSGateway_adv_system_systemComponentWrapper_internalPortId_t)ROSGATEWAY_ADV_SYSTEM_SYSTEMCOMPONENTWRAPPER_PORT_SENDSUM,
        XME_CORE_ATTRIBUTE_KEY_CHANNELID,
        (void*)requestDataHandle,
        (uint32_t)sizeof(xme_core_component_requestDataHandle_t)
    );
    XME_CHECK_MSG_REC
    (
        XME_STATUS_SUCCESS == status,
        status,
        {
            outputPorts[outputPortIndex].state.error = 1;
        },
        XME_LOG_ERROR,
        "%s:%d rOSGateway_adv_system_systemComponentWrapper_writeResponseSenderPortSendSum: Writing channel ID attribute to port failed. This is attribute is mandatory for request/response communication. Message cannot be delivered.\n",
        __FILE__,
        __LINE__
    );
    outputPorts[outputPortIndex].state.attributesValid = 1;

    // Write topic data
    status = xme_core_dataHandler_writeData
    (
        outputPorts[outputPortIndex].dataPacketId,
        (void*)data,
        (uint32_t)sizeof(ROSGateway_topic_sumResponse_t)
    );

    if (XME_STATUS_SUCCESS == status)
    {
        outputPorts[outputPortIndex].state.dataValid = 1;
    }
    else
    {
        outputPorts[outputPortIndex].state.error = 1;

        XME_LOG
        (
            XME_LOG_ERROR,
            "%s:%d rOSGateway_adv_system_systemComponentWrapper_writePortSendSum: Writing to port failed. Data Handler returned error code %d.",
            __FILE__,
            __LINE__,
            status
        );
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_readInputPortAttribute
(
    rOSGateway_adv_system_systemComponentWrapper_internalPortId_t portId,
    xme_core_attribute_key_t attributeKey,
    void* const buffer,
    uint32_t bufferSize
)
{
    xme_status_t status;
    uint8_t inputPortIndex;
    uint32_t bytesRead = 0U;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    inputPortIndex = (uint8_t)portId;

#ifdef XME_MULTITHREAD
    XME_ASSERT(inputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(inputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[inputPortIndex / 8U] & (1 << (inputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!inputPorts[inputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startReadOperation(inputPorts[inputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[inputPortIndex / 8U] |= (1 << (inputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        inputPorts[inputPortIndex].state.locked = 1;
    }

    status = xme_core_dataHandler_readAttribute
    (
        inputPorts[inputPortIndex].dataPacketId,
        attributeKey,
        buffer,
        bufferSize,
        &bytesRead
    );

    if (XME_STATUS_SUCCESS == status)
    {
        inputPorts[inputPortIndex].state.attributesValid = 1;
    }

    // FIXME: Check bytesRead

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_writeOutputPortAttribute
(
    rOSGateway_adv_system_systemComponentWrapper_internalPortId_t portId,
    xme_core_attribute_key_t attributeKey,
    const void* const buffer,
    uint32_t bufferSize
)
{
    xme_status_t status;
    uint8_t outputPortIndex;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    outputPortIndex = ((uint8_t)portId) - inputPortCount;

#ifdef XME_MULTITHREAD
    XME_ASSERT(outputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(outputPortAccessed);
    XME_ASSERT(NULL != accessed);

    if (!(accessed[outputPortIndex / 8U] & (1 << (outputPortIndex % 8U))))
#else // #ifdef XME_MULTITHREAD
    if (!outputPorts[outputPortIndex].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_startWriteOperation(outputPorts[outputPortIndex].dataPacketId);
        XME_CHECK(XME_STATUS_SUCCESS == status, XME_STATUS_INTERNAL_ERROR);
#ifdef XME_MULTITHREAD
        accessed[outputPortIndex / 8U] |= (1 << (outputPortIndex % 8U));
#endif // #ifdef XME_MULTITHREAD
        outputPorts[outputPortIndex].state.locked = 1;
    }

    status = xme_core_dataHandler_writeAttribute
    (
        outputPorts[outputPortIndex].dataPacketId,
        attributeKey,
        buffer,
        bufferSize
    );

    if (XME_STATUS_SUCCESS == status)
    {
        outputPorts[outputPortIndex].state.attributesValid = 1;
    }
    else
    {
        outputPorts[outputPortIndex].state.error = 1;

        XME_LOG
        (
            XME_LOG_ERROR,
            "%s:%d rOSGateway_adv_system_systemComponentWrapper_writeOutputPortAttribute: Writing to port failed. Data Handler returned error code %d.",
            __FILE__,
            __LINE__,
            status
        );
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_readNextPacket
(
    rOSGateway_adv_system_systemComponentWrapper_internalPortId_t portId
)
{
    xme_status_t status = XME_STATUS_SUCCESS;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    XME_ASSERT(portId < inputPortCount);

#ifdef XME_MULTITHREAD
    XME_ASSERT(inputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(inputPortAccessed);
    XME_ASSERT(NULL != accessed);

    // We need to complete the read operation if the port has been accessed
    if (accessed[portId / 8U] & (1 << (portId % 8U)))
#else // #ifdef XME_MULTITHREAD
    if (inputPorts[portId].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_completeReadOperation(inputPorts[portId].dataPacketId);
        XME_CHECK_MSG
        (
            XME_STATUS_SUCCESS == status,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "[systemComponentWrapper] CompleteReadOperation for port (interalPortId: %d, dataPacketId: %d) returned error code %d.\n",
            portId, inputPorts[portId].dataPacketId, status
        );

#ifdef XME_MULTITHREAD
        accessed[portId / 8U] &= ~(1 << (portId % 8U));
#endif // #ifdef XME_MULTITHREAD
        inputPorts[portId].state.dataValid = 0;
        inputPorts[portId].state.attributesValid = 0;
        inputPorts[portId].state.locked = 0;
        inputPorts[portId].state.error = 0;
    }

    return status;
}

xme_status_t
rOSGateway_adv_system_systemComponentWrapper_writeNextPacket
(
    rOSGateway_adv_system_systemComponentWrapper_internalPortId_t portId
)
{
    xme_status_t status = XME_STATUS_SUCCESS;
#ifdef XME_MULTITHREAD
    char* accessed;
#endif // #ifdef XME_MULTITHREAD

    XME_ASSERT(portId >= inputPortCount && portId < inputPortCount + outputPortCount);
    portId -= inputPortCount;

#ifdef XME_MULTITHREAD
    XME_ASSERT(outputPortAccessed != XME_HAL_TLS_INVALID_TLS_HANDLE);
    accessed = (char*) xme_hal_tls_get(outputPortAccessed);
    XME_ASSERT(NULL != accessed);

    // We need to complete the write operation if the port has been accessed
    if (accessed[portId / 8U] & (1 << (portId % 8U)))
#else // #ifdef XME_MULTITHREAD
    if (outputPorts[portId].state.locked)
#endif // #ifdef XME_MULTITHREAD
    {
        status = xme_core_dataHandler_completeWriteOperation(outputPorts[portId].dataPacketId);
        XME_CHECK_MSG
        (
            XME_STATUS_SUCCESS == status || XME_STATUS_NOT_FOUND == status || XME_STATUS_BUFFER_TOO_SMALL == status,
            XME_STATUS_INTERNAL_ERROR,
            XME_LOG_ERROR,
            "[systemComponentWrapper] CompleteWriteOperation for port (interalPortId: %d, dataPacketId: %d) returned error code %d.\n",
            portId + inputPortCount, outputPorts[portId], status
        );

#ifdef XME_MULTITHREAD
        accessed[portId / 8U] &= ~(1 << (portId % 8U));
#endif // #ifdef XME_MULTITHREAD
        outputPorts[portId].state.dataValid = 0;
        outputPorts[portId].state.attributesValid = 0;
        outputPorts[portId].state.locked = 0;
        outputPorts[portId].state.error = 0;

        if (XME_STATUS_BUFFER_TOO_SMALL == status)
        {
            XME_LOG
            (
                XME_LOG_WARNING,
                "[systemComponentWrapper] Data loss on port (interalPortId: %d, dataPacketId: %d), because of full buffer. Oldest value was overwritten.\n",
                portId + inputPortCount, outputPorts[portId]
            );
        }
    }

    return status;
}

